package test.administrator.example.com.mvptest1.framework.support;

import android.support.annotation.MainThread;
import android.support.annotation.NonNull;

import java.lang.ref.WeakReference;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import test.administrator.example.com.mvptest1.framework.MvpPresenter;
import test.administrator.example.com.mvptest1.framework.MvpView;

public class MvpQueuingBasePresenter<V extends MvpView> implements MvpPresenter<V> {

	public interface ViewAction<V> {
		void run(@NonNull V view);
	}

	private Queue<ViewAction<V>> viewActionQueue = new ConcurrentLinkedQueue<>();

	private WeakReference<V> viewRef;

	private boolean presenterDestroyed;

	@Override
	public void attachView(@NonNull V view) {
		presenterDestroyed = false;
		viewRef = new WeakReference<V>(view);
		runQueuedActions();
	}

	@Override
	public void detachView() {
		viewRef.clear();
	}

	@Override
	public void destroy() {
		viewActionQueue.clear();
		presenterDestroyed = false;
	}

	@MainThread
	protected final void onceViewAttached(ViewAction<V> action) {
		viewActionQueue.add(action);
		runQueuedActions();
	}

	private void runQueuedActions() {
		V view = viewRef == null ? null : viewRef.get();
		if (view != null) {
			while (!viewActionQueue.isEmpty()) {
				ViewAction<V> action = viewActionQueue.poll();
				action.run(view);
			}
		}
	}

	@MainThread
	protected final void ifViewAttached(boolean exceptionIfViewNotAttached, ViewAction<V> action) {
		final V view = viewRef == null ? null : viewRef.get();
		if (view != null) {
			action.run(view);
		} else if (exceptionIfViewNotAttached) {
			throw new IllegalStateException(
					"No View attached to Presenter. Presenter destroyed = " + presenterDestroyed);
		}
	}

	protected final void ifViewAttached(ViewAction<V> action) {
		ifViewAttached(false, action);
	}

}
